#light
namespace MPI.Bindings
#nowarn "0044";;  // suppress warnings about the use of native pointer features to interoperate with native code
#nowarn "0051";;  // suppress warnings about the use of byref features to interoperate with native code
#nowarn "0049";;  // turn off warnings about using upper case identifiers for variables (e.g. matrices)

open System.Runtime.InteropServices
open System
module MPIRaw = begin
    type MPI_Datatype = 
        | MPI_CHAR           =  0x4c000101
        | MPI_SIGNED_CHAR    =  0x4c000118
        | MPI_UNSIGNED_CHAR  =  0x4c000102
        | MPI_BYTE           =  0x4c00010d
        | MPI_WCHAR          =  0x4c00020e    
        | MPI_SHORT          =  0x4c000203
        | MPI_UNSIGNED_SHORT =  0x4c000204
        | MPI_INT            =  0x4c000405
        | MPI_UNSIGNED       =  0x4c000406
        | MPI_LONG_LONG_INT  =  0x4c000809
        | MPI_FLOAT          =  0x4c00040a
        | MPI_DOUBLE         =  0x4c00080b
        | MPI_UNSIGNED_LONG  =  0x4c000408
        | MPI_LONG           =  0x4c000407

    type MPI_OP  =
        | MPI_MAX     = 0x58000001
        | MPI_MIN     = 0x58000002
        | MPI_SUM     = 0x58000003
        | MPI_PROD    = 0x58000004
        | MPI_LAND    = 0x58000005
        | MPI_BAND    = 0x58000006
        | MPI_LOR     = 0x58000007
        | MPI_BOR     = 0x58000008
        | MPI_LXOR    = 0x58000009
        | MPI_BXOR    = 0x5800000a
        | MPI_MINLOC  = 0x5800000b
        | MPI_MAXLOC  = 0x5800000c
        | MPI_REPLACE = 0x5800000d

    // Communicators
    let MPI_COMM_WORLD = 0x44000000
    let MPI_COMM_SELF  = 0x44000001
    
    
    let MPI_SUCCESS = 0      

    [<StructLayout(LayoutKind.Sequential,Size=20)>]
    type MPI_Status = struct
        val count : int
        val cancelled : int
        val MPI_SOURCE : int
        val MPI_TAG : int
        val MPI_ERROR : int
    end

    type Ptr3Char = char nativeptr nativeptr  nativeptr

    [<DllImport(@"mpich2.dll",EntryPoint="MPI_Init")>]
    extern int MPI_Init(int *argc, Ptr3Char argv)

    [<DllImport(@"mpich2.dll",EntryPoint="MPI_Abort")>]
    extern int MPI_Abort(int comm, int errorcode )    
    
    [<DllImport(@"mpich2.dll",EntryPoint="MPI_Comm_size")>]
    extern int MPI_Comm_size(int MPI_Comm, int *size )

    [<DllImport(@"mpich2.dll",EntryPoint="MPI_Comm_rank")>]
    extern int MPI_Comm_rank(int MPI_Comm, int *rank)    

    [<DllImport(@"mpich2.dll",EntryPoint="MPI_Finalize")>]
    extern int MPI_Finalize()

    [<DllImport(@"mpich2.dll",EntryPoint="MPI_Send")>]
    extern int MPI_Send( void *buf, int count, int MPI_Datatype, int dest, int tag, int MPI_Comm)


    [<DllImport(@"mpich2.dll",EntryPoint="MPI_Recv")>]
    extern int MPI_Recv( void *buf, int count, int MPI_Datatype, int source, int tag, int MPI_Comm, MPI_Status *status )
      
    [<DllImport(@"mpich2.dll",EntryPoint="MPI_Barrier")>]
    extern int MPI_Barrier(int MPI_Comm );
    
    [<DllImport(@"mpich2.dll",EntryPoint="MPI_Bcast")>]
    extern int MPI_Bcast ( void *buffer, int count, int MPI_Datatype, int root, int MPI_Comm )

    [<DllImport(@"mpich2.dll",EntryPoint="MPI_Gather")>]
    extern int MPI_Gather ( void *sendbuf, int sendcnt, int MPI_Datatype ,  void *recvbuf, int recvcount, int MPI_Datatype , int root,int  MPI_Comm )

    [<DllImport(@"mpich2.dll",EntryPoint="MPI_Scatter")>]
    extern int MPI_Scatter ( void *sendbuf, int sendcnt, int MPI_Datatype, void *recvbuf,  int recvcnt,  int MPI_Datatype, 
                             int root, int MPI_Comm )   
    
    [<DllImport(@"mpich2.dll",EntryPoint="MPI_Reduce")>]
    extern int MPI_Reduce(void *sendbuf, void *recvbuf, int count,int MPI_Datatype,int MPI_Op , int root, int MPI_Comm )
end
(*                                
 int MPI_Testany(int count, MPI_Request *array_of_requests, int *index, int *flag, MPI_Status *status)
int MPI_Testall(int count, MPI_Request *array_of_requests,int *flag, MPI_Status *status)
int MPI_Testsome(int incount, MPI_Request *array_of_requests, int *outcount, int *array_of_indices, MPI_Status *array_of_statuses)
         int MPI_Waitany(int count, MPI_Request *array_of_requests, int *index, MPI_Status *status)
int MPI_Waitall(int count, MPI_Request *array_of_requests,MPI_Status *status)
int MPI_Waitsome(int incount, MPI_Request *array_of_requests, int *outcount, int *array_of_indices, MPI_Status *array_of_statuses)
MPI_Cart_Create (MPI_Comm old_comm,                 int number_of_dims,                 int dim_sizes[],                 int connected[],                 int reorder,                 MPI_Comm *cart_comm)
          ,MPI_ANY_SOURCE
          
MPI_Sendrecv
MPI_Sendrecv_replace
            
MPI_Graphdims_get	
MPI_Graph_get	
MPI_Graph_neighbors_count
MPI_Graph_neighbors	
            
            
MPI_Graph_create (MPI_Comm old_comm,                  int nnodes,                  int *index,                  int *edges,                  int reorder,                  MPI_Comm *comm_graph)
   
int MPI_Isend (void *buf, int count, MPI_Datatype datatype, int dest, int tag,MPI_Comm comm, MPI_Request *request)
int MPI_Irecv (void *buf, int count, MPI_Datatype datatype, int source, int tag,MPI_Comm comm, MPI_Request *request)
int MPI_Iprobe (int source, int tag,MPI_Comm comm, int *flag, MPI_status *status)

MPI_Ssend

MPI_Bsend
MPI_Ibsend

MPI_Rsend
MPI_Irsend


MPI_PUT 
MPI_GET 
MPI_ACCUMULATE 

MPI_Comm_group ( comm, group )
MPI_Group_excl ( group, n, ranks, newgroup )
MPI_Comm_create ( comm, group, comm_out )
MPI_Comm_free ( comm )         
           *)